package com.jiyici.view;

import java.util.ArrayList;

import jiyici.Constant.ItemParamType;
import jiyici.ParamType;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.TextView.OnEditorActionListener;

import com.jiyici.DragSortListView;
import com.jiyici.DragSortListView.DropListener;
import com.jiyici.R;
import com.jiyici.controller.DataManager;
import com.jiyici.model.Category;
import com.jiyici.model.Item;
import com.jiyici.model.ItemParam;
import com.jiyici.utils.SortOrder;
import com.jiyici.utils.StringUtils;
import com.jiyici.view.DialogUtil.Notify;
import com.jiyici.view.DialogWrapper.DialogAction;

public class ItemEditView extends LinearLayout {

    public ItemEditView(Context context, AttributeSet attrs) {
        super(context, attrs);
        inflate();
    }

    public ItemEditView(Context context) {
        super(context);
        inflate();
    }

    public void setItem(Item item) {
        mItem = item;
        mIsEdit = true;
        applyData2Ui();
    }

    public Item getItem() {
        applyUi2Data();
        return mItem;
    }
    
    public ArrayList<ItemParam> getDeletedItemParams() {
        return mDeletedParamList;
    }

    private void applyUi2Data() {
        mItem.itemName = StringUtils.trimToEmpty(mEditItemName.getText().toString());
        Category category = (Category) mEditCategory.getTag();
        if (category != null)
            mItem.categoryId = category.getId();
        mItem.params = mItemParamList;
    }

    private void applyData2Ui() {
        mEditItemName.setText(mItem.itemName);
        Category category = DataManager.getCategoryById(mItem.categoryId);
        if (category != null) {
            mEditCategory.setTag(category);
            mEditCategory.setText(category.name);
        }
        mItemParamList.addAll(mItem.params);
    }

    private void inflate() {
        mLayoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = mLayoutInflater.inflate(R.layout.view_edit_item, this, true);
        mEditItemName = (EditText) view.findViewById(R.id.edit_item_name);
        mEditCategory = (TextView) view.findViewById(R.id.edit_item_category);
        mBtnAddProperty = view.findViewById(R.id.add_property);
        mListViewProperty = (DragSortListView) view.findViewById(R.id.property_list);
        mPropertyAdapter = new PropertyAdapter();
        mListViewProperty.setAdapter(mPropertyAdapter);
        mListViewProperty.setDropListener(mPropertyAdapter);
        mListViewProperty.setOnItemClickListener(mPropertyAdapter);

        mEditCategory.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                displaySelectCategoryDialog(getContext());
            }
        });
        mEditCategory.setOnFocusChangeListener(new View.OnFocusChangeListener() {

            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus)
                    displaySelectCategoryDialog(getContext());
            }
        });

        mBtnAddProperty.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                displayAddPropertyView(getContext(), null);
            }
        });
    }

    class PropertyAdapter extends BaseAdapter implements DropListener, OnItemClickListener {

        @Override
        public int getCount() {
            return mItemParamList.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ItemPropertyView itemPropertyView = new ItemPropertyView(getContext());
            itemPropertyView.setParam(mItemParamList.get(position), this);
            return itemPropertyView;
        }

        public void deleteParam(ItemParam param) {
            mItemParamList.remove(param);
            if (param.getId() > 0)
                mDeletedParamList.add(param);
            notifyDataSetChanged();
        }

        @Override
        public void drop(int from, int to) {
            if (from == to)
                return;
            ItemParam param = mItemParamList.remove(from);
            mItemParamList.add(to, param);
            ItemParam prevItemParam = null;
            ItemParam nextItemParam = null;
            int index = to -1;
            if (index >= 0)
                prevItemParam = mItemParamList.get(index);
            index = to + 1;
            if (index < mItemParamList.size())
                nextItemParam = mItemParamList.get(index);
            param.displayOrder = SortOrder.Between(prevItemParam == null ? null : prevItemParam.displayOrder,
                    nextItemParam == null ? null : nextItemParam.displayOrder);
            param.dirty = true;
            notifyDataSetChanged();
        }

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            ItemParam itemParam = mItemParamList.get(position);
            displayAddPropertyView(getContext(), itemParam);
        }
    }

    private void displaySelectCategoryDialog(final Context context) {
        final DialogWrapper dialogWrapper = new DialogWrapper(context);
        dialogWrapper.setTitle(R.string.select_category);
        dialogWrapper.setContentView(R.layout.dialogbody_select_category);
        ListView categoryListView = (ListView) dialogWrapper.getContentView().findViewById(R.id.category_listview);
        DialogAction doneAction = new DialogAction() {

            @Override
            public int run() {
                displayNewCategoryDialog(context);
                return NOOP;
            }
        };
        DialogAction cancelAction = new DialogAction() {

            @Override
            public int run() {
                mEditCategory.setTag(null);
                mEditCategory.setText("");
                return DISMISS;
            }
        };
        dialogWrapper.setAction(R.string.new_category, doneAction, R.string.dialog_cancel, cancelAction);
        categoryListView.setAdapter(mCategoryAdapter);
        categoryListView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Category category = DataManager.getCategoryList().get(position);
                mEditCategory.setTag(category);
                mEditCategory.setText(category.name);
                dialogWrapper.dismiss();
            }

        });
        dialogWrapper.show();
    }

    private void displayNewCategoryDialog(final Context context) {
        final DialogWrapper dialogWrapper = new DialogWrapper(context);
        dialogWrapper.setTitle(R.string.new_category);
        dialogWrapper.setContentView(R.layout.dialogbody_add_category);
        final EditText edit_category_name = (EditText) dialogWrapper.getContentView().findViewById(
                R.id.edit_category_name);
        edit_category_name.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                dialogWrapper.getDoneButton().setEnabled(!StringUtils.isBlank(s.toString()));
            }
        });

        edit_category_name.setOnEditorActionListener(new OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (EditorInfo.IME_ACTION_DONE == actionId) {
                    String categoryName = edit_category_name.getText().toString();
                    if (StringUtils.isBlank(categoryName))
                        return false;
                    categoryName = StringUtils.trim(categoryName);
                    Category category = new Category();
                    category.name = categoryName;
                    DataManager.addCategory(category);
                    mCategoryAdapter.notifyDataSetChanged();
                    dialogWrapper.dismiss();
                    return true;
                }
                return false;
            }
        });

        DialogAction doneAction = new DialogAction() {

            @Override
            public int run() {
                String categoryName = edit_category_name.getText().toString();
                categoryName = StringUtils.trim(categoryName);
                if (StringUtils.isBlank(categoryName))
                    return NOOP;
                Category category = new Category();
                category.name = categoryName;
                DataManager.addCategory(category);
                mCategoryAdapter.notifyDataSetChanged();
                return DISMISS;
            }
        };
        dialogWrapper.setAction(R.string.dialog_done, doneAction, R.string.dialog_cancel, null);
        dialogWrapper.setBtnDoneInitailDisabled(true);
        dialogWrapper.show();
    }

    private void displayAddPropertyView(final Context context, final ItemParam itemParam) {
        final DialogWrapper dialogWrapper = new DialogWrapper(context);
        dialogWrapper.setContentView(R.layout.dialogbody_add_property);
        View dialogView = dialogWrapper.getContentView();

        final EditText edit_item_param_name = (EditText) dialogView.findViewById(R.id.edit_item_param_name);
        final CheckBox param_is_must = (CheckBox) dialogView.findViewById(R.id.param_is_must);

        final View typeViews[] = new View[ParamTypes.length];
        View.OnClickListener typeOnClickListener = new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                for (int i = 0; i < TypeViewIds.length; i++) {
                    boolean selected = v.getId() == TypeViewIds[i];
                    typeViews[i].setBackgroundResource(selected ? R.drawable.property_type_bg_selected
                            : R.drawable.property_type_bg);
                    TextView tv = (TextView) typeViews[i].findViewById(R.id.type_name);
                    tv.setTextColor(selected ? Color.rgb(0xee, 0xee, 0xee) : Color.rgb(0x33, 0x33, 0x33));
                    typeViews[i].setTag(selected ? Boolean.TRUE : Boolean.FALSE);
                }
            }
        };
        for (int i = 0; i < ParamTypes.length; i++) {
            typeViews[i] = dialogView.findViewById(TypeViewIds[i]);
            TextView tv = (TextView) typeViews[i].findViewById(R.id.type_name);
            tv.setText(ParamType.getParamType(ParamTypes[i]).typeName);
            typeViews[i].setOnClickListener(typeOnClickListener);
            typeViews[i].setTag(Boolean.FALSE);
        }
        
        if (itemParam != null) {
            edit_item_param_name.setText(itemParam.itemParamName);
            param_is_must.setChecked(itemParam.isMust);
            for (int i = 0; i < ParamTypes.length; i++) {
                if (itemParam.paramType == ParamTypes[i]) {
                    typeViews[i].performClick();
                }
                /* edit item param can't change its type */
                if (itemParam.getId() > 0) {
                    typeViews[i].setOnClickListener(new View.OnClickListener() {
                        
                        @Override
                        public void onClick(View v) {
                            if (Boolean.FALSE == v.getTag()) {
                                DialogUtil.showNofity(getContext(), Notify.NOTIFY_WHEN_TRY_TO_CHANGE_PARAM_TYPE);
                            }
                        }
                    });
                }
            }
        }
        
        DialogAction doneAction = new DialogAction() {

            @Override
            public int run() {
                String paramName = edit_item_param_name.getText().toString();
                boolean isMust = param_is_must.isChecked();
                int selectParamType = getSelectedParamType(typeViews);
                if (StringUtils.isBlank(paramName)) {
                    return NOOP;
                }
                if (selectParamType == 0)
                    return NOOP;
                ItemParam param = null;
                if (itemParam != null) {
                    param = itemParam;
                } else {
                    param = new ItemParam();
                    param.itemId = mItem.getId();
                    String displayOrder;
                    int size = mItemParamList.size();
                    if (size == 0) {
                        displayOrder = SortOrder.Initial();
                    } else {
                        displayOrder = SortOrder.After(mItemParamList.get(size - 1).displayOrder);
                    }
                    param.displayOrder = displayOrder;
                    mItemParamList.add(param);
                }
                
                if (!StringUtils.equal(param.itemParamName, paramName.trim())) {
                    param.itemParamName = paramName.trim();
                    param.dirty = true;
                }
                if (param.isMust != isMust) {
                    param.isMust = isMust;
                    param.dirty = true;
                }
                if (param.paramType != selectParamType) {
                    param.paramType = selectParamType;
                    param.dirty = true;
                }
                
                mPropertyAdapter.notifyDataSetChanged();
                return DISMISS;
            }
        };
        dialogWrapper.setAction(R.string.dialog_done, doneAction, R.string.dialog_cancel, null);
        dialogWrapper.show();
    }

    private static int getSelectedParamType(View[] typeViews) {
        for (int i = 0; i < typeViews.length; i++) {
            if (Boolean.TRUE.equals(typeViews[i].getTag())) {
                return ParamTypes[i];
            }
        }
        return 0;
    }

    private static int[] ParamTypes = { ItemParamType.TEXT, ItemParamType.NUMBER };
    private static int[] TypeViewIds = { R.id.type_text, R.id.type_number };

    private boolean mIsEdit = false;
    private EditText mEditItemName;
    private TextView mEditCategory;
    private View mBtnAddProperty;
    private DragSortListView mListViewProperty;
    private PropertyAdapter mPropertyAdapter;

    private Item mItem = new Item();
    private ArrayList<ItemParam> mItemParamList = new ArrayList<ItemParam>();
    /* only used in edit mode */
    private ArrayList<ItemParam> mDeletedParamList = new ArrayList<ItemParam>();
    private LayoutInflater mLayoutInflater;

    private CategoryAdapter mCategoryAdapter = new CategoryAdapter();;

    private class CategoryAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            ArrayList<Category> categories = DataManager.getCategoryList();
            if (categories == null)
                return 0;
            return categories.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView tv = (TextView) mLayoutInflater.inflate(R.layout.category_row, parent, false);
            Category category = DataManager.getCategoryList().get(position);
            tv.setText(category.name);
            boolean selected = category == mEditCategory.getTag();
            if (selected) {
                tv.setTextColor(getResources().getColor(R.color.actionbar_color));
                tv.setTypeface(Typeface.DEFAULT_BOLD);
            } else {
                tv.setTextColor(getResources().getColor(R.color.content_text));
                tv.setTypeface(Typeface.DEFAULT);
            }
            return tv;
        }

    }

}
